We shall say that an n-digit number is pandigital if it makes use of all the digits 1 to n exactly once; for example, the 5-digit number, 15234, is 1 through 5 pandigital.

The product 7254 is unusual, as the identity, 39 × 186 = 7254, containing multiplicand, multiplier, and product is 1 through 9 pandigital.

Find the sum of all products whose multiplicand/multiplier/product identity can be written as a 1 through 9 pandigital. HINT: Some products can be obtained in more than one way so be sure to only include it once in your sum.


In [4]:
39 * 186


Out[4]:
7254

In [5]:
12345.to_s


Out[5]:
"12345"

In [6]:
12345.to_s.split("")


Out[6]:
["1", "2", "3", "4", "5"]

In [7]:
123456789.to_s.split("")


Out[7]:
["1", "2", "3", "4", "5", "6", "7", "8", "9"]

In [8]:
target = 53241

123456789.to_s.split("").map { |item| target.to_s.split("").count(item) <= 1 }


Out[8]:
[true, true, true, true, true, true, true, true, true]

In [9]:
123456789.to_s.split("").all? { |item| target.to_s.split("").count(item) <= 1 }


Out[9]:
true

In [88]:
def pen_digital?(target)
  return false if target.to_s =~ /0/
  return 123456789.to_s.split("").all? { |item| target.to_s.split("").count(item) <= 1 }
end

pen_digital? 12345


Out[88]:
true

In [89]:
pen_digital? 29382


Out[89]:
false

In [90]:
def pen_digital_string?(target)
  return false if 123456789.to_s.split("").all? do |item|
    target.tr("*=", "").split("").count(item) <= 1
  end == false

  target =~ /(\d*?)\*(\d*?)=(\d*)$/
  return true if (($1.to_i * $2.to_i) == $3.to_i)
  return false
end

In [91]:
pen_digital_string?("123*123*1234")


Out[91]:
false

In [92]:
39 * 186


Out[92]:
7254

In [93]:
pen_digital_string?("39*186=7254")


Out[93]:
true

In [16]:
pen_digital_string?("123*456=789")


Out[16]:
false

In [98]:
def find_pen_digit_string32(num)
  return unless pen_digital?(num)

  result = []
  source = [1, 2, 3, 4, 5, 6, 7, 8, 9] - num.to_s.split("").map{|i| i.to_i}

  multiplicand = source.combination(3)
  multiplicand.each do |com|
    multiplier = source - com
    left = com.permutation(3).map{|a,b,c| [a,b,c]}
    right = multiplier.permutation(2).map{|a,b| [a,b]}

    strings = left.product(right).map do |arr|
      arr[0].join + "*" + arr[1].join + "=" + num.to_s
    end

    strings.each do |string|
      return num if pen_digital_string?(string)
    end
  end

  return 
end

find_pen_digit_string("1234")

In [99]:
find_pen_digit_string(7254)


Out[99]:
7254

In [117]:
result = []

(4140..9876).lazy.each do |i|
  temp = find_pen_digit_string(i)
  result << temp if temp != nil
end


Out[117]:
4140..9876

In [118]:
result


Out[118]:
[4396, 5346, 5796, 7254, 7632]

In [119]:
result.inject &:+


Out[119]:
30424

In [145]:
def find_pen_digit_string41(num)
  return unless pen_digital?(num)

  result = []
  source = [1, 2, 3, 4, 5, 6, 7, 8, 9] - num.to_s.split("").map{|i| i.to_i}

  multiplicand = source.combination(4)
  multiplicand.each do |com|
    multiplier = source - com
    left = com.permutation(4).map{|a,b,c,d| [a,b,c,d]}
    right = multiplier.permutation(1).map{|a| [a]}

    strings = left.product(right).map do |arr|
      arr[0].join + "*" + arr[1].join + "=" + num.to_s
    end

    strings.each do |string|
      return num if pen_digital_string?(string)
    end
  end

  return 
end

find_pen_digit_string41("1234")

In [146]:
result = []

(1234..9876).lazy.each do |i|
  temp = find_pen_digit_string41(i)
  result << temp if temp != nil
end


Out[146]:
1234..9876

In [147]:
result


Out[147]:
[6952, 7852]

In [148]:
30424 + 6952 + 7852


Out[148]:
45228